package lp2.projeto.horario;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * Representa um horario (ano, mes, dia, hora, minuto)
 */
public class Horario implements Comparable<Horario> , Serializable {

	private static final long serialVersionUID = 6367619450890164064L;
	/**
	 * Numero de horas em um dia
	 */
	public static final int HORAS_POR_DIA = 24;
	/**
	 * Numero de minutos em uma hora
	 */
	public static final int MINUTOS_POR_HORA = 60;
	
	private int ano, dia, hora, minuto;
	private Mes mes;
	
	/**
	 * Construtor padrao
	 * @param ano Ano
	 * @param mes Mes
	 * @param dia Dia, deve ser um dia valido para o mes e ano especificados
	 * @param hora Hora (deve ser entre 0 e 23, inclusive)
	 * @param minuto Minuto (deve entre 0 e 59, inclusive)
	 * @throws IllegalArgumentException Caso algum dos valores seja invalido
	 */
	public Horario(int ano, Mes mes, int dia, int hora, int minuto) throws IllegalArgumentException {
		if (mes == null)
			throw new IllegalArgumentException("Mes invalido");
		if (dia < 1 || dia > Mes.getNumDiasNoMes(mes, ano))
			throw new IllegalArgumentException("Dia invalido");
		if (hora < 0 || hora >= HORAS_POR_DIA)
			throw new IllegalArgumentException("Hora invalida");
		if (minuto < 0 || minuto >= MINUTOS_POR_HORA)
			throw new IllegalArgumentException("Minuto invalido");
		
		this.ano = ano;
		this.mes = mes;
		this.dia = dia;
		this.hora = hora;
		this.minuto = minuto;
	}
	
	/**
	 * Retorna um novo Horario, contendo a hora atual
	 * @return hora atual
	 */
	public static Horario getHoraAtual() {
		return new Horario(GregorianCalendar.getInstance());
	}
	
	/**
	 * Constroi um Horario com base em um Calendar
	 * @param calendar Calendar
	 */
	Horario(Calendar calendar) {
		ano = calendar.get(Calendar.YEAR);
		mes = Mes.values()[calendar.get(Calendar.MONTH)];
		dia = calendar.get(Calendar.DAY_OF_MONTH);
		hora = calendar.get(Calendar.HOUR_OF_DAY);
		minuto = calendar.get(Calendar.MINUTE);
	}

	/**
	 * Constroi um GregorianCalendar com o horario definido
	 * @return O GregorianCalendar
	 */
	Calendar toCalendar() {
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.YEAR, ano);
		calendar.set(Calendar.MONTH, mes.getNumero()-1);
		calendar.set(Calendar.DAY_OF_MONTH, dia);
		calendar.set(Calendar.HOUR_OF_DAY, hora);
		calendar.set(Calendar.MINUTE, minuto);
		return calendar;
	}
	
	/**
	 * @return o ano
	 */
	public int getAno() {
		return ano;
	}
	
	public void setAno(int ano) {
		this.ano = ano;
	}

	/**
	 * @return o mes
	 */
	public Mes getMes() {
		return mes;
	}
	
	public void setMes(Mes mes) {
		this.mes = mes;
	}

	/**
	 * @return o dia
	 */
	public int getDia() {
		return dia;
	}
	
	public void setDia(int dia) {
		this.dia = dia;
	}
	
	/**
	 * @return a hora
	 */
	public int getHora() {
		return hora;
	}
	
	public void setHora(int hora) {
		this.hora = hora;
	}
	/**
	 * @return o minuto
	 */
	public int getMinuto() {
		return minuto;
	}
	
	public void setMinuto(int minuto) {
		this.minuto = minuto;
	}
	
	/**
	 * Compara se dois horarios sao iguais
	 */
	@Override
	public boolean equals(Object obj) {
		Horario outro = (Horario)obj;
		return compareTo(outro) == 0;
	}
	
	/**
	 * Compara o horario atual com outro horario
	 * @param outro Outro horario para comparar
	 * @return < 0 Se este evento ocorrer antes, = 0 se ocorrerem ao mesmo tempo, > 0 se ocorrer depois 
	 */
	@Override
	public int compareTo(Horario outro) {
		if (ano != outro.ano)
			return ano - outro.ano;
		if (mes != outro.mes)
			return mes.getNumero() - outro.mes.getNumero();
		if (dia != outro.dia)
			return dia - outro.dia;
		if (hora != outro.hora)
			return hora - outro.hora;
		return minuto - outro.minuto;			
	}
	
	/**
	 * Retorna uma representacao em String to objeto
	 * @return A representacao
	 */
	@Override public String toString() {
		return dia + "/" + mes.getNumero() + "/" + ano + " " + hora + ":" + minuto;
	}
}
